package red.mlz.smsservice.scheduler;

import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import red.mlz.common.entity.sms.smslog.SmsLog;
import red.mlz.common.entity.sms.smstask.SmsTask;
import red.mlz.smsservice.service.smslog.SmsLogService;
import red.mlz.smsservice.service.smstask.SmsTaskService;

import java.util.List;

@Component
@Slf4j
public class SmsTaskScheduler {

    private static final int PAGE_SIZE = 50; // 每页处理的任务数量
    private static final int MAX_RETRY = 3;  // 最大重试次数

    @Autowired
    private SmsTaskService smsTaskService;

    @Autowired
    private SmsLogService smsLogService;

    // 每5秒执行一次
    @Scheduled(fixedRate = 30000)
    public void processSmsTasks() {
        int page = 0;
        List<SmsTask> tasks;
        do {
            // 1. 分页查询待处理任务（status=0）
            tasks = smsTaskService.findByStatusWithPaging(0, page, PAGE_SIZE);
            log.info("Processing page {} of pending SMS tasks, found {} tasks", page, tasks.size());

            // 2. 处理当前页的每个任务
            for (SmsTask task : tasks) {
                processTask(task);
            }

            page++;
        } while (!tasks.isEmpty()); // 3. 当没有任务时停止循环
    }

    private void processTask(SmsTask task) {
        log.debug("Processing SMS task: id={}, phone={}", task.getId(), task.getPhone());

        // 4. 使用乐观锁尝试获取任务
        boolean lockAcquired = smsTaskService.updateStatusWithOptimisticLock(
                task.getId(),
                0,   // 期望的旧状态（未发送）
                100  // 新状态（处理中）
        );

        if (!lockAcquired) {
            log.debug("Task {} already being processed by another instance", task.getId());
            return;
        }

        try {
            // 5. 发送短信
            SendSmsResponse response = sendSms(task);

            // 6. 记录短信日志
            createSmsLog(task, response);

            // 7. 更新任务状态为成功
            smsTaskService.updateStatus(task.getId(), 1);
            log.info("SMS sent successfully for taskId: {}, phone: {}", task.getId(), task.getPhone());
        } catch (Exception e) {
            log.error("Failed to send SMS for taskId: {}, phone: {}", task.getId(), task.getPhone(), e);

            // 8. 处理失败情况
            handleFailedTask(task, e);
        }
    }

    private void handleFailedTask(SmsTask task, Exception e) {
        // 获取当前重试次数
        int currentRetry = task.getRetryCount() != null ? task.getRetryCount() : 0;

        if (currentRetry < MAX_RETRY) {
            // 9. 增加重试次数
            smsTaskService.updateRetryCount(task.getId(), currentRetry + 1);
            log.info("Retry scheduled for taskId: {} (retry {}/{})",
                    task.getId(), currentRetry + 1, MAX_RETRY);
        } else {
            // 10. 超过最大重试次数，标记为失败
            smsTaskService.updateStatus(task.getId(), -1);
            log.error("Task {} failed after {} retries, marked as failed",
                    task.getId(), MAX_RETRY);

            // 11. 记录详细的失败日志
            createFailureLog(task, e);
        }
    }

    private SendSmsResponse sendSms(SmsTask task) throws ClientException {
        return smsLogService.sendSync(
                task.getPhone(),
                "阿里云短信测试",
                "SMS_154950909",
                "{\"code\":\"" + task.getContent() + "\"}"
        );
    }

    private void createSmsLog(SmsTask task, SendSmsResponse response) {
        int timestamp = (int) (System.currentTimeMillis() / 1000);
        SmsLog smsLog = new SmsLog();
        smsLog.setPhone(task.getPhone());
        smsLog.setContent("您的验证码：" + task.getContent());
        smsLog.setResult(response.getCode() + ":" + response.getMessage());
        smsLog.setSendTime(timestamp);
        smsLog.setCreateTime(timestamp);
        smsLog.setUpdateTime(timestamp);
        smsLog.setIsDeleted(0);
        smsLogService.insert(smsLog);
    }

    private void createFailureLog(SmsTask task, Exception e) {
        int timestamp = (int) (System.currentTimeMillis() / 1000);
        SmsLog smsLog = new SmsLog();
        smsLog.setPhone(task.getPhone());
        smsLog.setContent("您的验证码：" + task.getContent());
        smsLog.setResult("FAILED: " + e.getMessage());
        smsLog.setSendTime(timestamp);
        smsLog.setCreateTime(timestamp);
        smsLog.setUpdateTime(timestamp);
        smsLog.setIsDeleted(0);
        smsLogService.insert(smsLog);
    }
}